﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Security;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Timers;
using System.ServiceModel;
using MyWcfLib;
using WeatherService.DAC;
using WeatherService.Helpers;
using WeatherService.WCF;

namespace WeatherService
{
    public class ProcessScheduler
    {

        private System.Timers.Timer timer;




        private void OnElapsedTime(object source, ElapsedEventArgs e)
        {
            try
            {
                RunMethods();

            }
            catch { }


        }


        private static Int32 counter;//used to count 15 minutes so we don't call Alarm method every minute
        private static void RunMethods()
        {
            ThreadPool.QueueUserWorkItem(delegate {
                GetWeather.GetandApplyData();
                                             });

            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();


            //Force garbage collection.
            MinimizeMemory();
            
        }
        ServiceHost serviceHost = null;
        public static void MinimizeMemory()
        {
            GC.Collect(GC.MaxGeneration);
            GC.WaitForPendingFinalizers();
            SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, (UIntPtr)0xFFFFFFFF, (UIntPtr)0xFFFFFFFF);

            IntPtr heap = GetProcessHeap();

            if (HeapLock(heap))
            {
                try
                {
                    if (HeapCompact(heap, 0) == 0)
                    {
                        // error condition ignored 
                    }
                }
                finally
                {
                    HeapUnlock(heap);
                }
            }
        }
        [DllImport("kernel32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool SetProcessWorkingSetSize(IntPtr process, UIntPtr minimumWorkingSetSize, UIntPtr maximumWorkingSetSize);
        [DllImport("kernel32.dll", SetLastError = true)]
        internal static extern IntPtr GetProcessHeap();
        [DllImport("kernel32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool HeapLock(IntPtr heap);
        [DllImport("kernel32.dll")]
        internal static extern uint HeapCompact(IntPtr heap, uint flags);
        [DllImport("kernel32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool HeapUnlock(IntPtr heap);
        public void StartMethod(string[] args)
        {


            try
            {
                this.timer = new System.Timers.Timer();
                Logger.StatusLog("Starting Service");
                this.timer.Elapsed += this.OnElapsedTime;
                this.timer.Interval = 60000.0;
                this.timer.Enabled = true;
                
                //Add code that will execute on start.

                string m_port = "8732";


                var tcpBaseAddress = new Uri(string.Format("net.tcp://localhost:{0}/", m_port));
                serviceHost = new ServiceHost(typeof(MyWcfServer), tcpBaseAddress);

                var tcpBinding = new NetTcpBinding(SecurityMode.None, false);
                tcpBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;
                tcpBinding.Security.Transport.ProtectionLevel = ProtectionLevel.EncryptAndSign;

                serviceHost.AddServiceEndpoint(typeof(IMyWcfServiceControl), tcpBinding, string.Format("net.tcp://localhost:{0}/MyWcfServiceControl", m_port));

                //this is the default but good to know
                serviceHost.Authorization.PrincipalPermissionMode = System.ServiceModel.Description.PrincipalPermissionMode.UseWindowsGroups;

                serviceHost.Open();

                

            }
            catch (Exception exception)
            {
                //do your exception handling thing
                Logger.ErrorLog(exception.Message);
            }
        }


        public void StopMethod()
        {
            this.timer.Enabled = false;
            Logger.StatusLog("Stopping Service");
            //Add code that will execute on stop.
            if (serviceHost != null) serviceHost.Close();



        }
    }
}
